package multiNyID.Objek;
/*
 * class MarkerGroup
 *
 * bikin kelas untuk menghubungkan kumpulan multimarker
 * supaya mengacuke satu model
 * --------------------------------------------------------------------------------
 * Based On ColouredTiles.java
 * Andrew Davison, April 2005, ad@fivedots.coe.psu.ac.th
 *
 * @author whe_green@yahoo.co.id
 * Analisis Metode Occlusion Based Pada Augmented Reality
 * Studi Kasus Interaksi dengan Objek Virtual Secara Realtime
 * Menggunakan Gerakan Tangan
 *
 * Institut Teknologi Telkom
 * Fakultas Informatika 2007
 * Bandung Indonesia
 *
 * nyargreen.wordpress.com
 */

import com.sun.j3d.utils.image.TextureLoader;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.media.j3d.*;
import javax.vecmath.*;
import java.util.ArrayList;
import javax.imageio.ImageIO;

public class objekJ3D {

    private final static int FLOOR_LEN = 8;  // should be even
    // colours for floor, etc
    private final static Color3f green = new Color3f(0.0f, 0.5f, 0.1f);
    private final static Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
    private final static Color3f black = new Color3f(Color.BLACK);
    private final static Color3f red = new Color3f(Color.RED);
    private BranchGroup floorBG;

    public objekJ3D() // create tiles, add origin marker, then the axes labels
    {
        floorBG = new BranchGroup();

    }  // end of CheckerFloor()

    private void createCoords(int x, int z, ArrayList coords) // Coords for a single blue or green square,
    // its left hand corner at (x,0,z)
    {
//    float skala= 0.1f;
        // points created in counter-clockwise order
        Point3f p1 = new Point3f(x, -0.01f, z + 1.0f);
        Point3f p2 = new Point3f(x + 1.0f, -0.01f, z + 1.0f);
        Point3f p3 = new Point3f(x + 1.0f, -0.01f, z);
        Point3f p4 = new Point3f(x, -0.01f, z);

        coords.add(p1);
        coords.add(p2);
        coords.add(p3);
        coords.add(p4);
    }  // end of createCoords()

    public BranchGroup objek3DLoader(String fileName) {

        BranchGroup branchGroup = new BranchGroup();

        TransformGroup modelTG;    // untuk nampilin objek model

        PropManager modelPropMan = new PropManager(fileName, false);

        // get the TG for the prop (model)
        TransformGroup propTG = modelPropMan.getTG();

        // rotate and scale the prop
        Transform3D modelT3d = new Transform3D();
//        modelT3d.rotX(Math.PI / 2.0);
        // the prop lies flat on the marker; rotate forwards 90 degrees so it is standing
        Double skala = 0.25;
        Vector3d scaleVec = calcScaleFactor(propTG, skala);   // scale the prop
        modelT3d.setScale(scaleVec);

        modelTG = new TransformGroup(modelT3d);
        modelTG.addChild(propTG);

        branchGroup.addChild(modelTG);
        return branchGroup;
    }

    private Vector3d calcScaleFactor(TransformGroup modelTG, double scale) // Scale the prop based on its original bounding box size
    {
        BoundingBox boundbox = new BoundingBox(modelTG.getBounds());
//     System.out.println(boundbox);

        // obtain the upper and lower coordinates of the box
        Point3d lower = new Point3d();
        boundbox.getLower(lower);
        Point3d upper = new Point3d();
        boundbox.getUpper(upper);


        // store the largest X, Y, or Z dimension and calculate a scale factor
        double max = 0.0;
        if (Math.abs(upper.x - lower.x) > max) {
            max = Math.abs(upper.x - lower.x);
        }

        if (Math.abs(upper.y - lower.y) > max) {
            max = Math.abs(upper.y - lower.y);
        }

        if (Math.abs(upper.z - lower.z) > max) {
            max = Math.abs(upper.z - lower.z);
        }

        double scaleFactor = scale / max;
        System.out.printf("max dimension: %.3f;  scale factor: %.3f\n", max, scaleFactor);

        // limit the scaling so that a big model isn't scaled too much
        if (scaleFactor < 0.0005) {
            scaleFactor = 0.0005;
        }
        System.out.println("skaLA = " + scaleFactor);
        return new Vector3d(scaleFactor, scaleFactor, scaleFactor);
    }  // end of calcScaleFactor()

    public BranchGroup papanCatur() // A red square centered at (0,0,0), of length 0.5
    {  // points created counter-clockwise, a bit above the floor

        BranchGroup bg = new BranchGroup();

        ArrayList blackCoords = new ArrayList();
        ArrayList whiteCoords = new ArrayList();

        boolean isBlack;
        for (int z = -FLOOR_LEN / 2; z <= (FLOOR_LEN / 2) - 1; z++) { //-4 -3 -2 -1 0 1 2 3
            isBlack = (z % 2 == 0) ? true : false;    // set colour for new row
            for (int x = -FLOOR_LEN / 2; x <= (FLOOR_LEN / 2) - 1; x++) { //-4 -3 -2 -1 0 1 2 3
                if (isBlack) {
                    createCoords(x, z, blackCoords);
                } else {
                    createCoords(x, z, whiteCoords);
                }
                isBlack = !isBlack;
            }
        }
        bg.addChild(new ColouredTiles(blackCoords, black));
        bg.addChild(new ColouredTiles(whiteCoords, white));

        return bg;

    } // end of addOriginMarker();

    public BranchGroup Pointer(int i) {
        //bikin di ordinat 0.0 , 0.0 , 0.0

        Point3f p1 = new Point3f(-0.5f, 0.005f, -0.5f);
        Point3f p2 = new Point3f(0.5f, 0.005f, -0.5f);
        Point3f p3 = new Point3f(0.5f, 0.005f, 0.5f);
        Point3f p4 = new Point3f(-0.5f, 0.005f, 0.5f);

        ArrayList oCoords = new ArrayList();
        oCoords.add(p1);
        oCoords.add(p2);
        oCoords.add(p3);
        oCoords.add(p4);

        BranchGroup bg = new BranchGroup();
        if (i == 1) {
            bg.addChild(new ColouredTiles(oCoords, green));
        } else {
            bg.addChild(new ColouredTiles(oCoords, red));
        }
        p1 = new Point3f(-0.5f, 0.0f, -0.5f);
        p2 = new Point3f(0.5f, 0.0f, -0.5f);
        p3 = new Point3f(0.5f, 0.0f, 0.5f);
        p4 = new Point3f(-0.5f, 0.0f, 0.5f);

        oCoords = new ArrayList();
        oCoords.add(p1);
        oCoords.add(p2);
        oCoords.add(p3);
        oCoords.add(p4);

        bg.addChild(new ColouredTiles(oCoords, red));

        return bg;
    }

    public BranchGroup Gambar(String path) {
        BranchGroup objRoot = new BranchGroup();
        Transform3D transform = new Transform3D();
        Appearance appear = new Appearance();


        //  Create a Transform Group object
//  TransformGroup objTrans = new TransformGroup(movX);
        TransformGroup objTrans = new TransformGroup();
        objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);

        Transform3D rotTrans = new Transform3D();
        rotTrans.rotX(-Math.PI / 2.0);    // 3ds models are often on their face; fix that
        objTrans.setTransform(rotTrans);

        File f = new File(path);
        BufferedImage buffImage = null;
        try {
            buffImage = ImageIO.read(f);
            System.out.println("RUN");
        } catch (IOException e) {
            System.out.println("-->" + e);
        }

        TextureLoader loader = new TextureLoader(buffImage);
        ImageComponent2D imageTexture = loader.getImage();

        // can't use parameterless constuctor
        Texture2D texture = new Texture2D(
                Texture.BASE_LEVEL,
                Texture.RGBA,
                imageTexture.getWidth(),
                imageTexture.getHeight());

        texture.setImage(0, imageTexture);

        appear.setTexture(texture);

        appear.setTransparencyAttributes(
                new TransparencyAttributes(TransparencyAttributes.FASTEST,
                0.1f));

        // Create Geometry
//    Sphere sphere = new Sphere(1.0f, Primitive.GENERATE_TEXTURE_COORDS,
//appear);
        QuadArray plane = createPlane();  // initialize QuadArray object

        Shape3D planeObj = new Shape3D(plane, appear);
//  Shape3D sphereObj = new Shape3D(sphere, appear);

        // Key point - add the geometry not to the scene
        // but to the transformation object!
        objTrans.addChild(planeObj);

        //  add Transform group object to the Branch group
        objRoot.addChild(objTrans);

        Background background = new Background();
        background.setColor(0.0f, 0.0f, 0.5f);
        background.setApplicationBounds(new BoundingSphere());
        objRoot.addChild(background);

        return objRoot;
    }

    public QuadArray createPlane() {
        QuadArray plane =
                new QuadArray(4, GeometryArray.COORDINATES
                | GeometryArray.TEXTURE_COORDINATE_2);

        Point3f p = new Point3f(-1.0f, 1.0f, 0.0f);
        plane.setCoordinate(0, p);
        p.set(-1.0f, -1.0f, 0.0f);
        plane.setCoordinate(1, p);
        p.set(1.0f, -1.0f, 0.0f);
        plane.setCoordinate(2, p);
        p.set(1.0f, 1.0f, 0.0f);
        plane.setCoordinate(3, p);


        Point2f q = new Point2f(0.0f, 1.0f);
        plane.setTextureCoordinate(0, q);
        q.set(0.0f, 0.0f);
        plane.setTextureCoordinate(1, q);
        q.set(1.0f, 0.0f);
        plane.setTextureCoordinate(2, q);
        q.set(1.0f, 1.0f);
        plane.setTextureCoordinate(3, q);

        return plane;
    }

    public BranchGroup PointerGrid() {
        //bikin di ordinat 0.0 , 0.0 , 0.0

        Point3f p1 = new Point3f(-4.0f, 0.01f, 3.0f);
        Point3f p2 = new Point3f(-3.0f, 0.01f, 3.0f);
        Point3f p3 = new Point3f(-3.0f, 0.01f, 4.0f);
        Point3f p4 = new Point3f(-4.0f, 0.01f, 4.0f);

        ArrayList oCoords = new ArrayList();
        oCoords.add(p1);
        oCoords.add(p2);
        oCoords.add(p3);
        oCoords.add(p4);

        BranchGroup bg = new BranchGroup();
        bg.addChild(new ColouredTiles(oCoords, green));

        return bg;
    }

    public BranchGroup getFloorBG() {
        return floorBG;
    }
}  // end of CheckerFloor class

